package com.jiehoo.ooqi;

import java.io.Serializable;
import java.util.List;

/**
 * Search condition, used in where and having part of QL.
 */
public class Condition implements Serializable {
  private static final long serialVersionUID = -1830367471787528390L;

  /**
   * Condition field, can be null, for example, for not, and and or Condition.
   */
  private Field field;

  /**
   * Operator.
   */
  private Operator operator;

  /**
   * Condition value.
   */
  private Object value;

  /**
   * Constructor.
   */
  public Condition() {
  }

  /**
   * Constructor.
   *
   * @param field    search field name,search target model or table would be default From of QueryInfo.
   * @param operator operator
   * @param value    field value, can be another field, specific value, another condition or condition list.
   */
  public Condition(String field, Operator operator, Object value) {
    this.field = new Field(field);
    this.operator = operator;
    this.value = value;
  }

  /**
   * Constructor.
   *
   * @param field    search field.
   * @param operator operator
   * @param value    field value, can be another field, specific value, another condition or condition list.
   */
  public Condition(Field field, Operator operator, Object value) {
    this.field = field;
    this.operator = operator;
    this.value = value;
  }

  public Field getField() {
    return field;
  }

  public void setField(Field field) {
    this.field = field;
  }

  public Operator getOperator() {
    return operator;
  }

  public void setOperator(Operator operator) {
    this.operator = operator;
  }

  public Object getValue() {
    return value;
  }

  public void setValue(Object value) {
    this.value = value;
  }

  @SuppressWarnings("unchecked")
  public Condition addValue(Object value) {
    ((List<Object>) this.value).add(value);
    return this;
  }

  public String toString() {
    switch (operator) {
    case and:
    case or:
      return toStringFromList(operator.toString());
    case not:
      return "(" + operator + " " + value + ")";//value must be Condition
    case in:
      return field + " " + operator + toStringFromList(",");
    default:
      return field + " " + operator + " " + getValueString(value);
    }
  }

  /**
   * Convert value to string.
   * @param value value
   * @return null or string value
   */
  private String getValueString(Object value) {
    if (value == null) {
      return null;
    }
    if (value instanceof String) {
      return "'" + value + "'";
    } else {
      return value.toString();
    }
  }

  /**
   * Convert list value to string
   * @param separator separator
   * @return string value
   */
  protected String toStringFromList(String separator) {
    StringBuilder buffer = new StringBuilder();
    buffer.append("(");
    boolean isStart = true;
    for (Object object : (List<?>) value) {
      if (isStart) {
        isStart = false;
      } else {
        buffer.append(" ").append(separator).append(" ");
      }
      buffer.append(getValueString(object));
    }
    buffer.append(")");
    return buffer.toString();
  }
}
